package lang

import (
	"fmt"
	// "time"
)

type Buffer struct {
	number int
	pool   bool
}

var freeList = make(chan *Buffer, 10)
var serverChan = make(chan *Buffer)
var exitChan = make(chan int)

func mainLeakyBucket() {
	totalClient := 1
	totalServer := 2
	for i := 0; i < totalClient; i++ {
		go client()
	}

	for i := 0; i < totalServer; i++ {
		go server()
	}

	maxLength := 0
	count := 0
	for {
		length := <-exitChan
		if length > maxLength {
			maxLength = length
		}
		count++
		if count == (totalClient) {
			break
		}
	}

	fmt.Println(maxLength)
}

func client() {
	maxLength := 0
	for i := 0; i < 10; i += 1 {
		var b *Buffer
		// Grab a buffer if available; allocate if not.
		length := len(freeList)
		if length > maxLength {
			maxLength = length
		}
		if b = <-freeList; b != nil {
			fmt.Println("client, case: reuse ", b.number)
		} else {
			fmt.Println("client, case: allocating")
		}
		// select {
		// case b = <-freeList:
		// 	// Got one; nothing more to do.
		// 	fmt.Println("client, case: reuse ", b.number)
		// default:
		// 	fmt.Println("client, case: allocating")
		// 	// None free, so allocate a new one.
		// 	b = new(Buffer)
		// }
		load(b, i)      // Read next message from the net.
		serverChan <- b // Send to server.
	}
	exitChan <- maxLength
}

func server() {
	for {
		b := <-serverChan // Wait for work.
		process(b)
		// Reuse buffer if there's room.
		select {
		case freeList <- b:
			fmt.Println("server, case: refund ", b.number)
			// Buffer on free list; nothing more to do.
		default:
			// Free list full, just carry on.
			fmt.Println("server, case: free ", b.number)
		}
	}
}

func load(b *Buffer, i int) {
	b.number = i
	// time.Sleep(1_000_000)
}

func process(b *Buffer) {
	// fmt.Println("server: process ", b.number)
}
